package com.yeyks.shiro;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.yeyks.common.exception.TokenInvalidException;

import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class JWTUtil {

    /** token秘钥 */
    public static final String SECRET = "269e2643-b259-419c-bc4d-23b34d09f9f4";
    /** token 过期时间: 10天 */
    public static final int calendarField = Calendar.DATE;
    public static final int calendarInterval = 100;

    // 过期时间5分钟
    //private static final long EXPIRE_TIME = 5*24*60*60*1000;

    /**
     * 由当前用户ID创建对应Token，有效期为10天（calendarInterval * calendarField)
     * @param user_id
     * @return
     * @throws Exception
     */
    public static  String createToken(String user_id) {
        Date iatDate = new Date();
        // expire time
        Calendar nowTime = Calendar.getInstance();
        nowTime.add(calendarField, calendarInterval);
        Date expiresDate = nowTime.getTime();

        // header Map
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("alg", "HMAC256");
        map.put("type", "JWT");

        // build token
        // param backups {iss:Service, aud:APP}
        String token = JWT.create().withHeader(map) // header
                .withClaim("user_id", user_id)
                .withIssuedAt(iatDate) // sign time
                .withExpiresAt(expiresDate) // expire time
                .sign(Algorithm.HMAC256(SECRET)); // signature 对密码进行加密后再与用户名混淆在一起在签名时可以通过

        return token;
    }

    /**
     * 根据Token获取user_id
     *
     * @param token
     * @return user_id
     */
    public static  String getUserId(String token) throws TokenInvalidException {
        String user_id = null;
        try {
            Map<String, Claim> claims = getClaims(token);
            Claim user_id_claim = claims.get("user_id");
            user_id = user_id_claim == null ? null : user_id_claim.asString();
        } catch (Throwable e) {
            e.printStackTrace();
        }

        if (user_id == null) {
            throw new TokenInvalidException();
        }
        return user_id;
    }

    /**
     * 解密Token，获得内容
     *
     * @param token
     * @return
     * @throws Exception
     */
    public static Map<String, Claim> getClaims(String token) {
        JWTVerifier verifier = JWT.require(Algorithm.HMAC256(SECRET)).build();
        DecodedJWT jwt = verifier.verify(token);
        return (jwt == null || jwt.getClaims() == null) ? null : jwt.getClaims();
    }

    public static void main(String[] args) {
        String token = createToken("1403");
        System.out.println(token);
        try {
            System.out.println(getUserId(token));
        } catch (TokenInvalidException e) {
            e.printStackTrace();
        }
    }

//    // 过期时间5分钟
//    private static final long EXPIRE_TIME = 5*60*1000;
//
//    /**
//     * 校验token是否正确
//     * @param token 密钥
//     * @param secret 用户的密码
//     * @return 是否正确
//     */
//    public static boolean verify(String token, String username, String secret) {
//        try {
//            Algorithm algorithm = Algorithm.HMAC256(secret);
//            JWTVerifier verifier = JWT.require(algorithm)
//                    .withClaim("username", username)
//                    .build();
//            DecodedJWT jwt = verifier.verify(token);
//            return true;
//        } catch (Exception exception) {
//            return false;
//        }
//    }
//
//    /**
//     * 获得token中的信息无需secret解密也能获得
//     * @return token中包含的用户名
//     */
//    public static String getUsername(String token) {
//        try {
//            DecodedJWT jwt = JWT.decode(token);
//            return jwt.getClaim("username").asString();
//        } catch (JWTDecodeException e) {
//            return null;
//        }
//    }
//
//    /**
//     * 生成签名,5min后过期
//     * @param username 用户名
//     * @param secret 用户的密码
//     * @return 加密的token
//     */
//    public static String sign(String username, String secret) {
//        try {
//            Date date = new Date(System.currentTimeMillis()+EXPIRE_TIME);
//            Algorithm algorithm = Algorithm.HMAC256(secret);
//            // 附带username信息
//            return JWT.create()
//                    .withClaim("username", username)
//                    .withExpiresAt(date)
//                    .sign(algorithm);
//        } catch (Exception e) {
//            return null;
//        }
//    }
}
